#include "mythread.hpp"
#include "log.hpp"
#include <iostream>
#include <pthread.h>
#include <queue>
#include <vector>
#include <string>
#include <functional>
#include <time.h>

using namespace my_thread;

template <class T>
class ThreadPool
{
private:
    void Lock()
    {
        pthread_mutex_lock(&_mutex);
    }

    void Unlock()
    {
        pthread_mutex_unlock(&_mutex);
    }

    void ThreadSleep()
    {
        pthread_cond_wait(&_cond, &_mutex);
    }

    void WeakUpOneThread()
    {
        pthread_cond_signal(&_cond);
    }

    void WeakUpAllThread()
    {
        pthread_cond_broadcast(&_cond);
    }

    void doMission(const std::string &name)
    {
        // std::cout << "i am: " << name << std::endl;
        while (1)
        {
            Lock();
            // 如果线程池还在运行，但是任务队列为空
            // 那就让线程休眠，知道有任务
            while (_task_queue.empty() && _isrunning)
            {
                _wait_num++;
                ThreadSleep();
                _wait_num--;
            }
            // 如果线程池为空，但是任务队列已经停止
            // 那么直接让线程退出
            if (_task_queue.empty() && !_isrunning)
            {
                LOG(INFO, "%s out", name.c_str());
                std::cout << name << ": out" << std::endl;
                Unlock();
                break;
            }

            // 如果线程池不为空
            // 如果进程池还在运行，就正常执行任务；如果线程池已经停止，就先让线程处理完任务队列的任务再回到if语句退出
            T mission = _task_queue.front();
            LOG(INFO, "%s do missson", name.c_str());
            std::cout << name << " get mission: ";
            _task_queue.pop();

            Unlock();

            mission();
        }
    }

public:
    ThreadPool(int thread_num)
        : _thread_num(thread_num), _isrunning(false), _wait_num(0)
    {
        _threads.reserve(_thread_num);

        pthread_mutex_init(&_mutex, nullptr);
        pthread_cond_init(&_cond, nullptr);
    }

    //向任务队列插入任务
    bool enQueue(const T &task)
    {
        bool ret = false;

        Lock();
        if (_isrunning)
        {
            _task_queue.push(task);
            if (_wait_num)
                WeakUpOneThread();

            ret = true;
            LOG(INFO, "enQueue SUCCESS");
        }
        if (!ret)
            LOG(ERROR, "enQueue ERROR");
        Unlock();


        return ret;
    }

    //停止线程池
    void Stop()
    {
        Lock();
        _isrunning = false;
        WeakUpAllThread(); // 线程池停止之前要唤醒所有线程，让其完成任务队列剩余的任务
        Unlock();
        LOG(WORING, "ThreadPool Stop");
    }

    //初始化线程池
    void threadInit()
    {
        LOG(DEBUG, "threadInit() begin");
        for (int i = 0; i < _thread_num; i++)
        {
            std::string name = "thread-" + std::to_string(i + 1);
            _threads.emplace_back(std::bind(&ThreadPool::doMission, this, std::placeholders::_1), name);
        }

        _isrunning = true;
        LOG(INFO, "threadInit() end");
    }

    //启动线程池
    void threadStart()
    {
        LOG(DEBUG, "threadStart() begin");
        for (auto &thread : _threads)
            thread.Start();
        LOG(INFO, "threadStart() end");
    }

    void threadWait()
    {
        LOG(DEBUG, "threadWait() begin");
        for (auto &thread : _threads)
            thread.Join();
        LOG(INFO, "threadWait() end");
    }

    ~ThreadPool()
    {
        pthread_mutex_destroy(&_mutex);
        pthread_cond_destroy(&_cond);
    }

private:
    int _thread_num;
    std::vector<mythread> _threads;
    std::queue<T> _task_queue;

    pthread_mutex_t _mutex;
    pthread_cond_t _cond;

    int _wait_num;
    bool _isrunning;
};